package com.nowcoder.community.service;

import com.nowcoder.community.entity.User;
import com.nowcoder.community.utils.CommunityConstant;
import com.nowcoder.community.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FollowService implements CommunityConstant {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    //需要利用事务，在关注某个人的同时，被关注人的粉丝++
    public void follow(int userId, int entityType ,int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisUtil.getFollowerKey(entityType, entityId);
                //开始事务
                operations.multi();

                operations.opsForZSet().add(followeeKey, entityId,System.currentTimeMillis());
                operations.opsForZSet().add(followerKey,userId,System.currentTimeMillis());

                //提交事务
                return operations.exec();
            }
        });
    }

    //需要利用事务，在取消关注某个人的同时，被关注人的粉丝--
    public void unfollow(int userId, int entityType ,int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisUtil.getFollowerKey(entityType, entityId);
                //开始事务
                operations.multi();

                operations.opsForZSet().remove(followeeKey, entityId,System.currentTimeMillis());
                operations.opsForZSet().remove(followerKey,userId,System.currentTimeMillis());

                //提交事务
                return operations.exec();
            }
        });

    }

    /**
     * 查询关注的实体的数量（我的关注）
     * @param userId
     * @param entityType
     * @return
     */
    public long findFolloweeCount(int userId,int entityType){
        String followeeKey = RedisUtil.getFolloweeKey(userId,entityType);
        //返回集合中元素数量
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    /**
     * 查询实体的粉丝数量（我的粉丝）
     * @param entityType
     * @param entityId
     * @return
     */
    public long findFollowerCount(int entityType,int entityId){
        String followerKey = RedisUtil.getFollowerKey(entityType,entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    /**
     * 查询当前用户是否已关注该实体
     * @param userId
     * @param entityType
     * @param entityId
     * @return
     */
    public boolean hasFollower(int userId,int entityType, int entityId ){
        String followeeKey = RedisUtil.getFolloweeKey(userId,entityType);
        return redisTemplate.opsForZSet().score(followeeKey,entityId) != null;
    }

    /**
     * 查询某个用户关注的人(分页)
     * @param userId
     * @param offset
     * @param limit
     * @return
     */
    public List<Map<String, Object>> findFollowees(int userId, int offset,int limit){
        String followeesKey = RedisUtil.getFolloweeKey(userId,ENTITY_TYPE_USER);
        Set<Integer> ids = redisTemplate.opsForZSet().reverseRange(followeesKey, offset, offset + limit - 1);

        if (ids == null){
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer id:ids){
            User user = userService.findUserById(id);
            Map<String, Object> map = new HashMap<>();
            map.put("user",user);
            //关注时间
            Double score = redisTemplate.opsForZSet().score(followeesKey, id);
            map.put("followTime",new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }


    /**
     * 查询某个用户的粉丝(分页)
     * @param userId
     * @param offset
     * @param limit
     * @return
     */
    public List<Map<String, Object>> findFollowers(int userId, int offset,int limit){
        String followersKey = RedisUtil.getFollowerKey(ENTITY_TYPE_USER ,userId);
        Set<Integer> ids = redisTemplate.opsForZSet().reverseRange(followersKey, offset, offset + limit - 1);

        if (ids == null){
            return null;
        }

        List<Map<String, Object>> list = new ArrayList<>();
        for (Integer id:ids){
            User user = userService.findUserById(id);
            Map<String, Object> map = new HashMap<>();
            map.put("user",user);
            //关注时间
            Double score = redisTemplate.opsForZSet().score(followersKey, id);
            map.put("followTime",new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }

}
